package org.springframework.boot.netty.view;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import org.springframework.boot.autoconfigure.netty.NettyProperties;
import org.springframework.boot.netty.support.ModelAndView;
import org.springframework.boot.netty.support.TemplateWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;


/**
 * Author: huoxingzhi
 * Date: 2020/12/28
 * Email: hxz_798561819@163.com
 */
public class FreeMarkerView implements View {

    private Configuration configuration;

    private NettyProperties nettyProperties;

    public FreeMarkerView() {
    }

    public FreeMarkerView(NettyProperties nettyProperties) throws FileNotFoundException {
        this.nettyProperties = nettyProperties;
        if(null==configuration){
            bulitConfiguration(this.nettyProperties.getViewPrefix());
        }
    }

    /**
     * 构建Configuration
     * 在整个应用的生命周期中，这个后工作你应该只做一次  创建和调整配置
     * @return
     */
    private synchronized Configuration bulitConfiguration( String viewDir) throws FileNotFoundException {

        if(null==configuration){
            configuration = new Configuration(Configuration.VERSION_2_3_0);
            ClassLoader classLoader = FreeMarkerView.class.getClassLoader();
            File views = new File(classLoader.getResource(viewDir).getFile());
            try {
                configuration.setDirectoryForTemplateLoading(views);
                configuration.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_0));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return configuration;
        }
        return configuration;
    }

    @Override
    public void render(io.netty.channel.Channel channel, ModelAndView modelAndView) throws Exception {

        FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);

        Template template = getTemplate(modelAndView.getView() + nettyProperties.getViewSuffix());
        TemplateWriter writer = new TemplateWriter();
        template.process(modelAndView.getModel(), writer);
        String body = writer.getBody();
        ByteBuf buffer = Unpooled.copiedBuffer(body.getBytes("UTF-8"));
        response.content().writeBytes(buffer);

        response.headers().set(HttpHeaderNames.CONTENT_TYPE, HTML);
        // 需要渲染,不缓存
        response.headers().set(HttpHeaderNames.EXPIRES, "Thu, 01-Jan-1970 00:00:00 GMT");
        response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        response.headers().set(HttpHeaderNames.SERVER, SERVER);

        buffer.release();
        channel.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);

    }


    /**
     * 获取模板Template
     * @param ftlName
     * @return
     */
    private Template getTemplate(String ftlName){
        try {
            Template template = this.configuration.getTemplate(ftlName);
            return template;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }



}
